//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<CXmlFileHandler.cpp>
///	@path	~/src/database/xres/
///	@date	2007/12/03
///	@desc	.

#include "config/config.h"

#include "database/IData.h"
#include "database/xdata/CXmlNodeData.h"
#include "database/xres/CXmlFileHandler.h"
#include "database/xres/xml_parser.h"

namespace xeres {

	IMPL_IOBJECT_CLASS( CXmlFileHandler );

	// CXmlFileHandler
	CXmlFileHandler::CXmlFileHandler( void )
	{

	}

	// ~CXmlFileHandler
	CXmlFileHandler::~CXmlFileHandler( void )
	{

	}

	namespace
	{
		/*!
			\class		_XmlEntryParser
			\brief		Parse XML & turns it to data entry.
		*/
		class _XmlEntryParser : public XmlParser
		{
		public:
			//@ ctor
			_XmlEntryParser( const WString& path )
				: m_path( path )
			{
			}

			// @dtor
			virtual ~_XmlEntryParser( void )
			{
			}

		public:
		// @interface

			/*!
				\brief		Call while parsing element and step in.
			*/
			virtual bool OnElementBegin( const WString& element )
			{
				//TRACE_INFO( _S("Adding element %s -> %s") , m_hierarchy.back()->GetKey().GetCStr() , element.c_str() );
				if( m_root.IsNull() )
				{
					m_root = new CXmlNodeData( Key::MakeKey( m_path ) );
					m_hierarchy.push_back( m_root );
				}
				else
				{
					if( m_hierarchy.size() == 0 )
					{
						TRACE_ERROR( _S("CXmlFileHandler::_XmlEntryParser: <%s> has more than one root entry.")
							, m_path.c_str() );
						return false;
					}
					// create new child & advance hierarchy
					RefPass<IData> entry = m_hierarchy.back()->NewChild( Key::MakeKey( element ) );
					m_hierarchy.push_back( entry );
				}
				return true;
			}

			/*!
				\brief		Call while parsing element attribute.
			*/
			virtual bool OnAttribute( const WString& name , const WString& attr )
			{
				return m_hierarchy.back()->SetAttribute( name , attr );
			}

			/*!
				\brief		Call while parsing element value.
			*/
			virtual bool OnValue( const WString& data )
			{
				// FIXME! identify value here

				m_hierarchy.back()->SetString( data );
				return true;
			}

			/*!
				\brief		Call while parsing element end.
			*/
			virtual bool OnElementEnd( void )
			{
				m_hierarchy.pop_back();
				return true;
			}

		//@ local

			/*!
				\brief		Get root of hierarchy.
			*/
			RefPass<IData> GetRoot( void )
			{
				return m_root;
			}

		private:

		//@ data

			std::vector< Ref< CXmlNodeData > >		m_hierarchy;
			Ref< CXmlNodeData >					m_root;
			WString									m_path;

		};

	}

	// LoadFile
	RefPass<IData> CXmlFileHandler::LoadFile( const Key& ext , RefWeak<IFile> file )
	{
		WString path = file->GetPath();
		normalize_slash( path.begin() , path.end() , '/' );
		size_t last = path.find_last_of('/');
		path = path.substr( last + 1 );
		_XmlEntryParser parser( path );
		if( !parser.ParseFile( file ) )
		{
			return NULL;
		}
		return parser.GetRoot();
	}

} // namespace xeres
